import customtkinter as ctk
from PIL import Image
import threading
import logging
from tkinter import messagebox
from concurrent.futures import ThreadPoolExecutor
import time


class GalleryView(ctk.CTkFrame):
    def __init__(self, parent, image_files, thumbnail_size=(100, 100), select_callback=None):
        super().__init__(parent)
        self.image_files = image_files
        self.thumbnail_size = thumbnail_size
        self.thumbnail_cache = {}
        self.thumbnail_sizes_cache = {}  # 新增
        self.current_page = 1
        self.total_pages = 1
        self.thumbnails_per_page = 0
        self.visible_images = []
        self.select_callback = select_callback

        self.executor = ThreadPoolExecutor(max_workers=4)

        self.create_gallery_view()
        self.update_gallery()

    def create_gallery_view(self):
        self.grid_columnconfigure(0, weight=1)
        self.grid_rowconfigure(0, weight=1)

        # 获取当前外观模式
        appearance_mode = ctk.get_appearance_mode()

        # 获取前景颜色
        fg_color = ctk.ThemeManager.theme["CTkFrame"]["fg_color"]

        # 根据外观模式选择适当的颜色
        if isinstance(fg_color, (tuple, list)):
            if appearance_mode == "Light":
                bg_color = fg_color[0]
            else:
                bg_color = fg_color[1]
        else:
            bg_color = fg_color

        self.gallery_canvas = ctk.CTkCanvas(self, bg=bg_color, highlightthickness=0)
        self.gallery_canvas.grid(row=0, column=0, sticky="nsew")

        self.gallery_scrollbar = ctk.CTkScrollbar(self, command=self.gallery_canvas.yview)
        self.gallery_scrollbar.grid(row=0, column=1, sticky="ns")

        self.gallery_canvas.configure(yscrollcommand=self.gallery_scrollbar.set)
        self.gallery_canvas.bind('<Configure>', self.on_gallery_canvas_configure)

        self.gallery_inner_frame = ctk.CTkFrame(self.gallery_canvas)
        self.gallery_canvas.create_window((0, 0), window=self.gallery_inner_frame, anchor="nw")

        self.pagination_frame = ctk.CTkFrame(self)
        self.pagination_frame.grid(row=1, column=0, columnspan=2, pady=10)

        self.prev_page_button = ctk.CTkButton(self.pagination_frame, text="上一页", command=self.prev_page)
        self.prev_page_button.pack(side="left", padx=5)

        self.page_label = ctk.CTkLabel(self.pagination_frame, text="第 1 页")
        self.page_label.pack(side="left", padx=5)

        self.page_entry = ctk.CTkEntry(self.pagination_frame, width=50)
        self.page_entry.pack(side="left", padx=5)

        self.go_to_page_button = ctk.CTkButton(self.pagination_frame, text="跳转", command=self.go_to_page)
        self.go_to_page_button.pack(side="left", padx=5)

        self.next_page_button = ctk.CTkButton(self.pagination_frame, text="下一页", command=self.next_page)
        self.next_page_button.pack(side="left", padx=5)

        # 添加缩略图大小调整滑块
        self.size_label = ctk.CTkLabel(self.pagination_frame, text="缩略图大小")
        self.size_label.pack(side="right", padx=5)

        self.thumbnail_size_slider = ctk.CTkSlider(
            self.pagination_frame,
            from_=50,
            to=200,
            number_of_steps=15,
            command=self.on_thumbnail_size_change
        )
        self.thumbnail_size_slider.set(self.thumbnail_size[0])
        self.thumbnail_size_slider.pack(side="right", padx=5)

    def on_thumbnail_size_change(self, value):
        new_size = int(float(value))
        self.thumbnail_size = (new_size, new_size)
        self.thumbnail_cache.clear()
        self.thumbnail_sizes_cache.clear()  # 清除尺寸缓存
        self.update_gallery()

    def update_gallery(self):
        self.calculate_gallery_layout()
        self.clear_gallery()
        self.load_visible_images()
        self.update_pagination_controls()

    def calculate_gallery_layout(self):
        canvas_width = self.gallery_canvas.winfo_width()
        if canvas_width == 1:
            canvas_width = self.gallery_canvas.winfo_toplevel().winfo_width()
        max_thumbnail_width = self.thumbnail_size[0]
        self.thumbnails_per_row = max(1, canvas_width // (max_thumbnail_width + 10))
        rows_per_page = 3
        self.thumbnails_per_page = self.thumbnails_per_row * rows_per_page
        self.total_pages = max(1, (len(self.image_files) + self.thumbnails_per_page - 1) // self.thumbnails_per_page)
        self.current_page = min(max(1, self.current_page), self.total_pages)

    def clear_gallery(self):
        for widget in self.gallery_inner_frame.winfo_children():
            widget.destroy()

    def load_visible_images(self):
        start_index = (self.current_page - 1) * self.thumbnails_per_page
        end_index = min(start_index + self.thumbnails_per_page, len(self.image_files))
        self.visible_images = self.image_files[start_index:end_index]
        self.render_thumbnails()

    def render_thumbnails(self):
        for idx, image_path in enumerate(self.visible_images):
            row, col = divmod(idx, self.thumbnails_per_row)
            frame = ctk.CTkFrame(self.gallery_inner_frame)
            frame.grid(row=row, column=col, padx=5, pady=5)
            # frame.grid_propagate(True)  # 确保frame根据内容自动调整大小

            label = ctk.CTkLabel(frame, text="加载中...")
            label.pack()
            if self.select_callback:
                label.bind("<Button-1>", lambda e, path=image_path: self.select_callback(path))

            # 异步加载缩略图
            self.executor.submit(self.load_and_set_thumbnail, image_path, label)

    def load_and_set_thumbnail(self, image_path, label):
        # 检查缓存
        if image_path in self.thumbnail_cache:
            thumbnail = self.thumbnail_cache[image_path]
            image_size = self.thumbnail_sizes_cache[image_path]
        else:
            try:
                with Image.open(image_path) as img:
                    # 计算缩放比例，保持宽高比
                    img_ratio = img.width / img.height
                    max_width, max_height = self.thumbnail_size
                    if img.width > img.height:
                        new_width = min(max_width, img.width)
                        new_height = int(new_width / img_ratio)
                    else:
                        new_height = min(max_height, img.height)
                        new_width = int(new_height * img_ratio)
                    img = img.resize((new_width, new_height), Image.LANCZOS)
                    thumbnail = ctk.CTkImage(light_image=img.copy(), dark_image=img.copy(), size=(new_width, new_height))
                    self.thumbnail_cache[image_path] = thumbnail
                    self.thumbnail_sizes_cache[image_path] = (new_width, new_height)
                    image_size = (new_width, new_height)
            except Exception as e:
                logging.error(f"Error loading thumbnail for {image_path}: {e}")
                return

        # 更新UI需要在主线程进行
        def set_thumbnail():
            label.configure(image=thumbnail, text="")
            label.image = thumbnail  # 防止被垃圾回收
            # 调整 label 的尺寸
            label.configure(width=image_size[0], height=image_size[1])
            if self.select_callback:
                label.bind("<Button-1>", lambda e, path=image_path: self.select_callback(path))

        self.after(0, set_thumbnail)

    def update_pagination_controls(self):
        self.page_label.configure(text=f"第 {self.current_page} 页，共 {self.total_pages} 页")
        self.prev_page_button.configure(state="normal" if self.current_page > 1 else "disabled")
        self.next_page_button.configure(state="normal" if self.current_page < self.total_pages else "disabled")

    def prev_page(self):
        if self.current_page > 1:
            self.current_page -= 1
            self.update_gallery()

    def next_page(self):
        if self.current_page < self.total_pages:
            self.current_page += 1
            self.update_gallery()

    def go_to_page(self):
        try:
            page_number = int(self.page_entry.get())
            if 1 <= page_number <= self.total_pages:
                self.current_page = page_number
                self.update_gallery()
                self.page_entry.delete(0, 'end')
            else:
                messagebox.showerror("无效的页码", "请输入一个有效的页码。")
        except ValueError:
            messagebox.showerror("无效的输入", "请输入一个有效的页码。")

    def on_gallery_canvas_configure(self, event):
        self.gallery_canvas.configure(scrollregion=self.gallery_canvas.bbox("all"))
